# view/user.py
import os

import mysql.connector
#导入蓝图类
from flask import Blueprint, request, jsonify
from flask import current_app
# 密码加密模块
from werkzeug.security import generate_password_hash, check_password_hash
import re
# 导入jwt
import jwt
from datetime import datetime, UTC, timedelta

from werkzeug.utils import secure_filename

# 导入连接数据库的组件
from public.sql_connect import get_connent

# 导入token验证的一块
from public.token import token_required, token_required_with_refresh

# 创建用户蓝图
user = Blueprint('user_print', __name__,template_folder='templates')


# 用户注册
@user.route('/register', methods=['POST'])
def register():
    try:
        # 检查 Content-Type 是否为 application/json
        if request.content_type != 'application/json':
            return jsonify({
                "code": -1,
                "msg": "客户端发送的请求格式不正确, Content-Type must be application/json",
                "data": None
            }), 415
        print("请求参数：：：",request.get_json())
        # {'account': '12345678', 'password': 'a123456'}
        data = request.get_json()

        if not data:
            return jsonify({"code": -1, "msg": "请求数据不能为空", "data": None}), 400

        account = data.get('account', '').strip()
        password = data.get('password', '').strip()

        print("请求参数：：：", type(account), account)

        # 参数完整性校验
        if not account or not password:
            return jsonify({"code": -1, "msg": "账号和密码不能为空", "data": None}), 400

        # 格式校验
        if not re.fullmatch(r'^\S{6,20}$', account):
            return jsonify({
                "code": -1,
                "msg": "账号必须是6-20位纯数字",
                "data": None
            }), 400

        if not re.fullmatch(r'^[A-Za-z0-9]{6,25}$', password):
            return jsonify({
                "code": -1,
                "msg": "密码必须是6-25位字母或数字组合",
                "data": None
            }), 400

        # 数据库连接
        conn = get_connent()  # 替换为你的数据库连接
        cursor = conn.cursor(dictionary=True)

        # 检查账号是否存在
        cursor.execute("SELECT account FROM users WHERE account = %s", (account,))
        if cursor.fetchone():
            conn.close()
            return jsonify({
                "code": -1,
                "msg": "账号已被注册",
                "data": None
            }), 409

        # 密码加密
        hashed_password = generate_password_hash(password, method='pbkdf2:sha256', salt_length=16)

        # 创建新用户
        cursor.execute(
            "INSERT INTO users (account, pwd, created_at, updated_at) VALUES (%s, %s, NOW(), NOW())",
            (account, hashed_password)
        )
        conn.commit()
        conn.close()

        return jsonify({
            "code": 0,
            "msg": "注册成功",
            "data": {
                "account": account,
            }
        }), 200

    except Exception as e:
        if 'conn' in locals():
            conn.rollback()
            conn.close()
        return jsonify({
            "code": -1,
            "msg": f"111服务器错误: {str(e)}",
            "data": None
        }), 500


# 用户登录
@user.route('/login', methods=['POST'])
def login():
    try:
        # 判断请求头的格式
        if request.content_type != 'application/json':
            return jsonify({
                "code": -1,
                "msg": "客户端发送的请求格式不正确, Content-Type must be application/json",
                "data": None
            }), 400
        # 获取请求体
        data = request.get_json()
        if not data:
            return jsonify({
                "code": -1,
                "msg": "未提供请求参数",
                "data": None
            }), 400
        # 获取参数
        account = data.get('account', '').strip()
        password = data.get('password', '').strip()
        # 需要的参数不能为空
        if not account or not password:
            return jsonify({
                "code": -1,
                "msg": "账号和密码不能为空",
                "data": None
            })
        # 连接数据库
        conn = get_connent()
        cursor = conn.cursor(dictionary=True)
        cursor.execute("SELECT id, account, pwd FROM users WHERE account = %s", (account,))
        user_info = cursor.fetchone()
        # 检查用户信息是否存在
        if user_info is None:
            conn.close()
            return jsonify({
                "code": -1,
                "msg": "您当前的账号不存在",
                "data": None
            })
        user_pwd = user_info['pwd']
        # 对比两个密码
        pwd_is_true = check_password_hash(user_pwd, password)
        # 检查用户密码是否正确
        if not pwd_is_true:
            conn.close()
            return jsonify({
                "code": -1,
                "msg": "当前用户密码错误",
                "data": None
            })
        payload = {
            'id': user_info['id'],
            "account": user_info['account'],
            'exp': datetime.now(UTC) + timedelta(hours=24)  # 明确使用 UTC 时区
        }
        token = jwt.encode(payload, current_app.config['SECRET_KEY'], algorithm='HS256')
        return jsonify({
            "code": 0,
            "msg": "登录成功",
            "data": {
                "account": user_info['account'],
                "id": user_info['id'],
                "token": token
            }
        })

    except mysql.connector.Error as err:
        if 'conn' in locals():
            conn.rollback()
            conn.close()
        return jsonify({
            "code": -1,
            "msg": f"服务器报错：{err}",
            "data": None
        })


# 用户退出
@user.route('/logout', methods=['POST'])
@token_required
def logout(current_user_id ,current_user_account):
    try:
        conn = get_connent()
        cursor = conn.cursor(dictionary=True)
        cursor.execute("SELECT id, account FROM users WHERE id = %s", (current_user_id,))
        user_info = cursor.fetchone()
        if user_info is None:
            conn.close()
            return jsonify({
                "code": -1,
                "msg": "当前用户不存在",
                "data": None
            })
        return jsonify({
            "code": 0,
            "msg": "退出登录成功",
            "data": {
                "account": user_info['account'],
                "id": user_info['id'],
            }
        })
    except mysql.connector.Error as err:
        if 'conn' in locals():
            conn.rollback()
            conn.close()
        return jsonify({
            "code": -1,
            "msg": f"服务器错误：{err}",
            "data": None
        })


# 获取用户个人信息
@user.route('/get/<int:user_id>', methods=['GET'])
@token_required
@token_required_with_refresh
def get(current_user_id ,current_user_account, user_id):
    try:
        # 连接
        conn = get_connent()
        cursor = conn.cursor(dictionary=True)
        # 执行
        cursor.execute(
        "SELECT id, account, mobile, created_at, updated_at, gender, picture, nickname, birth_date, address, profession FROM users WHERE id = %s",
        (user_id,))
        # 获取
        user_info = cursor.fetchone()
        # 判断
        if user_info is None:
            conn.close()
            return jsonify({
                "code": -1,
                "msg": "当前用户不存在",
                "data": None
            })
        # 返回
        return jsonify({
            "code": 0,
            "msg": "个人信息获取成功",
            "data": {
                "id": user_info['id'],
                "account": user_info['account'],
                "mobile": user_info['mobile'],
                "created_at": user_info['created_at'],
                "updated_at": user_info['updated_at'],
                "gender": user_info['gender'],
                "picture": user_info['picture'],
                "nickname": user_info['nickname'],
                "birth_date": user_info['birth_date'],
                "address": user_info['address'],
                "profession": user_info['profession']
            }
        })
    # 错误
    except mysql.connector.Error as err:
        if 'conn' in locals():
            conn.rollback()
            conn.close()
        # 返回
        return jsonify({
            "code": -1,
            "msg": f"服务器错误：{err}",
            "data": None
        })


# 修改用户的个人信息
@user.route('/update/<int:user_id>', methods=['PUT'])
@token_required
@token_required_with_refresh
def update(current_user_id ,current_user_account, user_id):
    try:
        # 检查 Content-Type 是否为 application/json
        if request.content_type != 'application/json':
            return jsonify({
                "code": -1,
                "msg": "客户端发送的请求格式不正确, Content-Type must be application/json",
                "data": None
            }), 415
        # 连接
        conn = get_connent()
        cursor = conn.cursor(dictionary=True)
        # 取参+验证
        data = request.get_json()
        if not data:
            return jsonify({
                "code": -1,
                "msg": "请提供请求参数",
                "data": None
            })
        '''
            "gender" : "男",
            "mobile" : "15512345678",
            "nickname": "鸿鹄",
            "birth_date" : "2007-02-02 02:02:02",
            "address": "湖北省点军区",
            "profession": "程序员"
        '''
        mobile = data.get('mobile', '')
        gender = data.get('gender', '')
        nickname = data.get('nickname', '')
        birth_date = data.get('birth_date', '')
        address = data.get('address', '')
        profession = data.get('profession', '')
        if not mobile or not gender or not nickname or not birth_date or not address or not profession:
            return jsonify({
                "code": -1,
                "msg": "缺少必要参数",
                "data": None
            })
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return jsonify({
                "code":-1,
                "msg": "手机号格式不正确",
                "data": None
            })
        if gender not in ['男', '女', '未知']:
            return jsonify({
                "code": -1,
                "msg": "性别格式不正确",
                "data": None
            })
        # 执行
        cursor.execute(
            """UPDATE users 
               SET 
                   gender = %s, 
                   mobile = %s, 
                   nickname = %s, 
                   birth_date = %s, 
                   address = %s, 
                   profession = %s,
                   updated_at = NOW()
               WHERE id = %s""",
            (gender, mobile, nickname, birth_date, address, profession, user_id)
        )
        conn.commit()
        return jsonify({
            "code": 0,
            "msg": "用户信息修改成功",
            "data": {
                "gender": gender,
                "mobile": mobile,
                "nickname": nickname,
                "birth_date": birth_date,
                "address": address,
                "profession": profession,
            }
        })
    # 错误
    except mysql.connector.Error as err:
        if 'conn' in locals():
            conn.rollback()
            conn.close()
        # 返回
        return jsonify({
            "code": -1,
            "msg": f"服务器错误：{err}",
            "data": None
        })


# 文件上传
@user.route('/upload', methods=['POST'])
@token_required
@token_required_with_refresh
def upload(current_user_id ,current_user_account):
    print("图片信息：：",request.files)
    if 'file' not in request.files:
        return jsonify({
            "code": -1,
            "msg": "当前未上传图片,字段为file",
            "data": None
        }),400
    file = request.files['file']
    if file.filename == '':
        return jsonify({
            "code": -1,
            "msg": "当前未上传图片,文件为空",
            "data": None
        }),400
    # 允许的文件类型
    ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif', 'webp'}
    MAX_FILE_SIZE = 5 * 1024 * 1024  # 5MB

    # 验证文件类型
    def allowed_file(filename):
        return '.' in filename and \
            filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

    if not allowed_file(file.filename):
        return jsonify({
            "code": -1,
            "msg": f"不支持的文件类型，仅支持: {', '.join(ALLOWED_EXTENSIONS)}",
            "data": None
        }), 400

    # 验证文件大小
    file.seek(0, os.SEEK_END)
    file_length = file.tell()
    file.seek(0)

    if file_length > MAX_FILE_SIZE:
        return jsonify({
            "code": -1,
            "msg": f"文件大小超过限制({MAX_FILE_SIZE // (1024 * 1024)}MB)",
            "data": None
        }), 400
    try:
        conn = get_connent()
        cursor = conn.cursor(dictionary=True)

        # 创建上传目录(如果不存在)
        upload_folder = current_app.config.get('UPLOAD_FOLDER', 'static/users')
        if not os.path.exists(upload_folder):
            os.makedirs(upload_folder)

        # 生成安全的文件名和路径
        filename = secure_filename(file.filename)
        # 添加时间戳防止重名
        timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
        unique_filename = f"{timestamp}_{current_user_id}_{filename}"
        filepath = os.path.join(upload_folder, unique_filename)

        # 保存文件
        file.save(filepath)

        # 构建可访问的URL
        file_url = f"/{upload_folder}/{unique_filename}"

        # 更新用户头像信息到数据库
        cursor.execute(
            "UPDATE users SET picture = %s WHERE id = %s",
            (file_url, current_user_id)
        )

        if cursor.rowcount == 0:
            conn.rollback()
            # 删除已上传的文件
            if os.path.exists(filepath):
                os.remove(filepath)
            return jsonify({
                "code": -1,
                "msg": "用户不存在",
                "data": None
            }), 404

        conn.commit()

        return jsonify({
            "code": 0,
            "msg": "文件上传成功",
            "data": {
                "url": file_url,
                "filename": unique_filename,
                "size": file_length
            }
        })

    except Exception as e:
        conn.rollback()
        current_app.logger.error(f"文件上传失败: {str(e)}")
        # 如果发生错误，删除可能已部分上传的文件
        if 'filepath' in locals() and os.path.exists(filepath):
            os.remove(filepath)
        return jsonify({
            "code": -1,
            "msg": "文件上传失败",
            "data": None
        }), 500
    finally:
        cursor.close()
        conn.close()


# 文件删除
@user.route('/delete_file', methods=['DELETE'])
@token_required
@token_required_with_refresh
def delete_file(current_user_id ,current_user_account):
    # 获取要删除的文件URL或文件名
    print("文件路径：",request.get_json())
    data = request.get_json()
    if not data or 'file_url' not in data:
        return jsonify({
            "code": -1,
            "msg": "请提供要删除的文件URL",
            "data": None
        }), 400

    file_url = data['file_url']

    try:
        conn = get_connent()
        cursor = conn.cursor(dictionary=True)

        # 1. 验证该文件是否属于当前用户
        cursor.execute(
            "SELECT picture FROM users WHERE id = %s AND picture = %s",
            (current_user_id, file_url)
        )
        user = cursor.fetchone()

        if not user:
            return jsonify({
                "code": -1,
                "msg": "文件不存在或不属于当前用户",
                "data": None
            }), 404

        # 2. 从文件系统中删除文件
        upload_folder = current_app.config.get('UPLOAD_FOLDER', 'static/users')

        # 从URL中提取文件名
        filename = os.path.basename(file_url)
        filepath = os.path.join(upload_folder, filename)

        if os.path.exists(filepath):
            os.remove(filepath)
        else:
            # 文件不存在于文件系统，但数据库中记录存在
            return jsonify({
                "code": -1,
                "msg": "文件不存在",
                "data": None
            }), 404

        # 3. 清空数据库中的文件记录
        cursor.execute(
            "UPDATE users SET picture = NULL WHERE id = %s",
            (current_user_id,)
        )

        conn.commit()

        return jsonify({
            "code": 0,
            "msg": "文件删除成功",
            "data": None
        })

    except Exception as e:
        conn.rollback()
        current_app.logger.error(f"文件删除失败: {str(e)}")
        return jsonify({
            "code": -1,
            "msg": "文件删除失败",
            "data": None
        }), 500
    finally:
        cursor.close()
        conn.close()


# 用户列表
@user.route('/list', methods=['GET'])
@token_required
def list(current_user_id ,current_user_account):
    data = request.get_json()
    if not data:
        return jsonify({"code": -1, "msg": "请求参数为空", "data": None})

    # 参数处理
    page = int(data.get('page', 1))
    page_size = int(data.get('page_size', 10))
    offset = (page - 1) * page_size
    account = data.get('account')

    # SQL构建
    base_sql = '''
               SELECT id,
                      account,
                      mobile,
                      created_at,
                      updated_at,
                      gender,
                      picture,
                      nickname,
                      birth_date,
                      address,
                      profession
               FROM users
               WHERE 1 = 1
               '''
    count_sql = 'SELECT COUNT(*) AS total FROM users WHERE 1=1'

    # 参数存储（按SQL条件顺序）
    params = []
    count_params = []

    # 账户筛选条件
    if account:
        base_sql += ' AND account LIKE %s'
        count_sql += ' AND account LIKE %s'
        like_param = f'%{account}%'
        params.append(like_param)
        count_params.append(like_param)

    # 分页
    base_sql += ' ORDER BY created_at DESC LIMIT %s OFFSET %s'
    params.extend([page_size, offset])

    # 执行查询
    conn = get_connent()
    cursor = conn.cursor(dictionary=True)
    try:
        # 主查询
        cursor.execute(base_sql, tuple(params))
        user_list = cursor.fetchall()

        # COUNT查询
        cursor.execute(count_sql, tuple(count_params))
        total_count = cursor.fetchone()['total']

        return jsonify({
            "code": 0,
            "msg": "用户列表请求成功",
            "data": {"list": user_list, "total": total_count}
        })
    except Exception as e:
        return jsonify({"code": -1, "msg": f"数据库错误: {str(e)}", "data": None})
    finally:
        cursor.close()
        conn.close()

# 用户状态更改
@user.route('/state_update/<int:user_id>', methods=['PUT'])
@token_required
def state_update(current_user_id ,current_user_account, user_id):
    try:
        data = request.get_json()
        if not data:
            return jsonify({
                "code": -1,
                "msg": "请提供请求参数",
                "data": None
            }),400
        status = data.get('status')
        if not status:
            return jsonify({
                "code": -1,
                "msg": "缺少必要参数",
                "data": None
            }),400
        conn = get_connent()
        cursor = conn.cursor(dictionary=True)
        cursor.execute(
            'UPDATE users SET status = %s WHERE id = %s',
            (status, user_id)
        )
        conn.commit()
        if not cursor.rowcount == 0:
            conn.rollback()
            return jsonify({
                "code": 0,
                "msg": "用户状态修改成功",
                "data": {
                    "status": status,
                    "user_id": user_id,
                }
            })
        return jsonify({
            "code": -1,
            "msg": "数据库无变化",
            "data": None
        }),500
        # 错误
    except mysql.connector.Error as err:
        if 'conn' in locals():
            conn.rollback()
            conn.close()
        # 返回
        return jsonify({
            "code": -1,
            "msg": f"服务器错误：{err}",
            "data": None
        })

# 用户删除
@user.route('/delete/<int:user_id>', methods=['DELETE'])
@token_required
def delete(current_user_id ,current_user_account, user_id):
    try:
        if not user_id:
            return jsonify({
                "code": -1,
                "msg": "请提供目标用户的id",
                "data": None
            })
        conn = get_connent()
        cursor = conn.cursor(dictionary=True)
        cursor.execute(
            'SELECT status FROM users WHERE id = %s',
            (user_id,)
        )
        user_status = cursor.fetchone().get('status')
        if user_status is not 1:
            return jsonify({
                "code": -1,
                "msg": "只有禁用的用户可以删除",
                "data": None
            })
        cursor.execute(
            'DELETE FROM users WHERE id = %s',
            (user_id,)
        )
        conn.commit()
        if not cursor.rowcount == 0:
            conn.rollback()
            return jsonify({
                "code": 0,
                "msg": "用户删除成功",
                "data": {
                    "user_id": user_id,
                }
            })
    except mysql.connector.Error as err:
        if 'conn' in locals():
            conn.rollback()
            conn.close()
        # 返回
        return jsonify({
            "code": -1,
            "msg": f"服务器错误：{err}",
            "data": None
        })

